#include "freqgaincurve.h"
#include "dm/dmdef.h"

FreqGainCurve::FreqGainCurve(QWidget *parent)
    : AWidget{parent}
    , m_selected{-1}
{
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

void FreqGainCurve::setList(const QList<DMVariant> &list)
{
    m_ctrlVect.clear();
    for(int i = 0; i < list.size(); ++i) {
        std::visit(
            overloaded {
                [this, i](const EQ &eq) {
                    m_ctrlVect.push_back(CtrlButtonGroup(ratio(), eq, QString::number(i + 1)));
                },
                [this](const Xover &xover) {
                    switch (xover.type) {
                    case XoverType::Hpf:
                        m_ctrlVect.push_back(CtrlButtonGroup(ratio(),xover, tr("H")));
                        break;
                    case XoverType::Lpf:
                        m_ctrlVect.push_back(CtrlButtonGroup(ratio(),xover, tr("L")));
                        break;
                    }
                }
            }, list.at(i));

    }
    update();
}

void FreqGainCurve::updateCtrl(const int &index, const DMVariant &dm)
{
    if (index > -1 && index < m_ctrlVect.size()) {
        m_ctrlVect[index].setDm(dm);
        m_selected = index;
        update();
    }
}

void FreqGainCurve::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

    auto pen = painter.pen();
    pen.setWidth(1);
    painter.setPen(pen);
    // 阴影
    if (-1 != m_selected) {
        std::vector<QPointF> cps(EQ_FREQUENCY_COUNT + 2);
        if (cps.empty()) {
            return;
        }
        // 阴影部分起始和结束点为0dB线两端
        cps.front() = QPointF(rect().bottomLeft().x(), height() * EQ_GAIN_MAX / EQ_GAIN_LENGTH);
        for (size_t i = 1; i < cps.size() - 1; ++i) {
            cps[i] = CtrlButtonGroup::toPoint(size(), EQ_FREQUENCY.at(i - 1), m_ctrlVect.at(m_selected).array.at(i - 1));
        }
        cps.back() = QPointF(rect().bottomRight().x(), height() * EQ_GAIN_MAX / EQ_GAIN_LENGTH);

        pen.setWidth(1);
        pen.setColor(QColor(119, 192, 51, 64));
        painter.setPen(pen);
        painter.setBrush(QColor(119, 192, 51, 48));

        painter.drawPath(getPath(cps));
    }

    // 频率曲线
    pen.setWidth(2);
    pen.setColor(QColor(119, 192, 51));
    painter.setPen(pen);
    painter.setBrush(Qt::NoBrush);

    std::vector<QPointF> tps(EQ_FREQUENCY.size());
    for (size_t i = 0; i < EQ_FREQUENCY.size(); ++i) {
        double tgain = 0.0;
        for (auto it = m_ctrlVect.constBegin(); it != m_ctrlVect.constEnd(); ++it) {
            tgain += it->array.at(i);
        }
        tps[i] = CtrlButtonGroup::toPoint(size(), EQ_FREQUENCY.at(i), tgain);
    }

    if (tps.empty()) {
        return;
    }
    painter.drawPath(getPath(tps));
    // 拖拽控件
    pen.setWidth(1);
    for (auto it = m_ctrlVect.begin(); it != m_ctrlVect.end(); ++it) {
        it->draw(painter, size());
    }
}

void FreqGainCurve::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        for (int i = 0; i < m_ctrlVect.size(); ++i) {
            if (m_ctrlVect.at(i).contains(event->pos())) {
                m_ctrlVect[i].setSelect(event->pos());
                m_selected = i;
            }
            else {
                m_ctrlVect[i].deselect();
            }
        }
        update();
    }

    QWidget::mousePressEvent(event);
}

void FreqGainCurve::mouseMoveEvent(QMouseEvent *event)
{
    setCursor(Qt::ArrowCursor);

    for (int i = 0; i < m_ctrlVect.size(); ++i) {
        if (m_ctrlVect.at(i).contains(event->pos())) {
            setCursor(Qt::PointingHandCursor);
            break;
        }
    }
    if (-1 != m_selected) {
        if (m_ctrlVect.at(m_selected).dragging()) {
            emit stateChanged(m_selected, m_ctrlVect.at(m_selected).newDm(event->pos(), size()));
        }
    }
}

void FreqGainCurve::mouseReleaseEvent(QMouseEvent *event)
{
    if (-1 != m_selected && event->button() == Qt::LeftButton) {
        m_ctrlVect[m_selected].dragCancel();
    }
    QWidget::mouseReleaseEvent(event);
}

QPainterPath FreqGainCurve::getPath(const std::vector<QPointF> &vect) const
{
    QPainterPath tpath;
    if (vect.empty()) {
        return tpath;
    }

    // 单个点：画标记
    if (vect.size() == 1) {
        tpath.addEllipse(vect.at(0), 2, 2);
        return tpath;
    }

    tpath.moveTo(vect.at(0));

    // 两个点：直接直线连接
    if (vect.size() == 2) {
        tpath.lineTo(vect.at(1));
        return tpath;
    }

    // 多个点：三次贝塞尔，控制点沿线段方向
    for (size_t i = 0; i < vect.size() - 1; ++i) {
        QPointF curr = vect.at(i);
        QPointF next = vect.at(i + 1);
        QPointF dir = next - curr; // 线段的方向向量

        // 控制点沿线段延长线（scale调整弯曲程度，0.2为推荐值，可微调）
        const qreal scale = 0.25;
        QPointF ctrl1 = curr + dir * scale;   // 第一个控制点（沿curr→next方向）
        QPointF ctrl2 = next - dir * scale;   // 第二个控制点（沿next→curr方向）

        tpath.cubicTo(ctrl1, ctrl2, next);
    }

    return tpath;
}
